package com.quanxiaoha.xiaohashu.gateway.exception;


import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.quanxiaoha.framework.common.response.Response;
import com.quanxiaoha.xiaohashu.gateway.enums.ResponseCodeEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @Author: jingyan_liu
 * @CreateTime: 2025-07-13
 * @Description:
 * @Version: 1.0
 */


@Component
@Slf4j
@RequiredArgsConstructor
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
	
	private final ObjectMapper objectMapper;
	
	@Override
	public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
		// 获取响应对象
		ServerHttpResponse response = exchange.getResponse();
		
		log.error("==> 全局异常捕获: ", ex);
		
		// 响参
		Response<?> result;
		// 根据捕获的异常类型，设置不同的响应状态码和响应消息
		if (ex instanceof NotLoginException) { // 未登录异常
			// 设置 401 状态码
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			// 构建响应结果
			result = Response.fail(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), ex.getMessage());
		} else if (ex instanceof NotPermissionException) { // 无权限异常
			// 权限认证失败时，设置 401 状态码
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			// 构建响应结果
			result = Response.fail(ResponseCodeEnum.UNAUTHORIZED.getErrorCode(), ex.getMessage());
		} else { // 其他异常，则统一提示 “系统繁忙” 错误
			result = Response.fail(ex.getMessage());
		}
		
		
		// 设置响应头的内容类型为 application/json;charset=UTF-8，表示响应体为 JSON 格式
		response.getHeaders().setContentType(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
		// 设置 body 响应体
		return response.writeWith(Mono.fromSupplier(() -> { // 使用 Mono.fromSupplier 创建响应体
			DataBufferFactory bufferFactory = response.bufferFactory();
			try {
				// 使用 ObjectMapper 将 result 对象转换为 JSON 字节数组
				return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
			} catch (Exception e) {
				// 如果转换过程中出现异常，则返回空字节数组
				return bufferFactory.wrap(new byte[0]);
			}
		}));
	}
}

